/**
 * 错误类型枚举
 */
export enum ErrorType {
	NETWORK = 'network',
	BUSINESS = 'business',
	RUNTIME = 'runtime',
	PERMISSION = 'permission',
	VALIDATION = 'validation',
}

/**
 * 错误信息接口
 */
export interface ErrorInfo {
	type: ErrorType
	message: string
	code?: string | number
	stack?: string
	timestamp: number
	url?: string
	userAgent?: string
	userId?: string
	context?: string
}

/**
 * 错误处理器类
 */
export class ErrorHandler {
	private static instance: ErrorHandler
	private errorLog: ErrorInfo[] = []
	private maxLogSize = 100

	private constructor() {
		this.setupGlobalErrorHandler()
	}

	static getInstance(): ErrorHandler {
		if (!ErrorHandler.instance) {
			ErrorHandler.instance = new ErrorHandler()
		}
		return ErrorHandler.instance
	}

	/**
	 * 设置全局错误处理器
	 */
	private setupGlobalErrorHandler() {
		// 捕获JavaScript运行时错误
		window.addEventListener('error', (event) => {
			this.handleError({
				type: ErrorType.RUNTIME,
				message: event.message,
				stack: event.error?.stack,
				timestamp: Date.now(),
				url: event.filename,
			})
		})

		// 捕获Promise未处理的rejection
		window.addEventListener('unhandledrejection', (event) => {
			this.handleError({
				type: ErrorType.RUNTIME,
				message: event.reason?.message || 'Unhandled Promise Rejection',
				stack: event.reason?.stack,
				timestamp: Date.now(),
			})
		})

		// 捕获资源加载错误
		window.addEventListener(
			'error',
			(event) => {
				if (event.target !== window) {
					this.handleError({
						type: ErrorType.NETWORK,
						message: `Resource loading failed: ${(event.target as any)?.src || (event.target as any)?.href}`,
						timestamp: Date.now(),
					})
				}
			},
			true
		)
	}

	/**
	 * 判断是否为可忽略的错误
	 * @param error 错误对象
	 * @returns boolean
	 */
	private isIgnorableError(error: Error): boolean {
		const ignorableMessages = [
			'Script error',
			'Non-Error promise rejection captured',
			'Network request failed',
			'ResizeObserver loop completed with undelivered notifications',
			'ResizeObserver loop limit exceeded',
			'Loading chunk',
			'Loading CSS chunk',
		]

		return ignorableMessages.some((msg) => {
			const message = error.message || ''
			const name = error.name || ''
			return message.includes(msg) || name.includes(msg)
		})
	}

	/**
	 * 处理错误
	 */
	handleError(errorInfo: Partial<ErrorInfo>) {
		// 过滤可忽略的错误
		if (this.isIgnorableError(new Error(errorInfo.message || ''))) {
			return
		}

		const fullErrorInfo: ErrorInfo = {
			type: errorInfo.type || ErrorType.RUNTIME,
			message: errorInfo.message || 'Unknown error',
			code: errorInfo.code,
			stack: errorInfo.stack,
			timestamp: errorInfo.timestamp || Date.now(),
			url: errorInfo.url || window.location.href,
			userAgent: navigator.userAgent,
			userId: this.getCurrentUserId(),
			context: errorInfo.context,
		}

		// 添加到错误日志
		this.addToLog(fullErrorInfo)

		// 上报错误（可以根据需要实现）
		this.reportError(fullErrorInfo)

		// 开发环境下在控制台显示错误
		if (import.meta.env.DEV) {
			console.error('Error caught:', fullErrorInfo)
		}
	}

	/**
	 * 添加到错误日志
	 */
	private addToLog(errorInfo: ErrorInfo) {
		this.errorLog.unshift(errorInfo)
		if (this.errorLog.length > this.maxLogSize) {
			this.errorLog = this.errorLog.slice(0, this.maxLogSize)
		}
	}

	/**
	 * 获取当前用户ID（需要根据实际情况实现）
	 */
	private getCurrentUserId(): string | undefined {
		// 这里可以从store或其他地方获取用户ID
		return undefined
	}

	/**
	 * 上报错误
	 */
	private reportError(errorInfo: ErrorInfo) {
		// 这里可以实现错误上报逻辑
		// 例如发送到错误监控服务
		if (import.meta.env.PROD) {
			// 只在生产环境上报
			// fetch('/api/error-report', {
			//   method: 'POST',
			//   headers: { 'Content-Type': 'application/json' },
			//   body: JSON.stringify(errorInfo)
			// }).catch(() => {
			//   // 忽略上报失败
			// })
		}
	}

	/**
	 * 获取错误日志
	 */
	getErrorLog(): ErrorInfo[] {
		return [...this.errorLog]
	}

	/**
	 * 清空错误日志
	 */
	clearErrorLog() {
		this.errorLog = []
	}

	/**
	 * 手动报告错误
	 */
	reportCustomError(type: ErrorType, message: string, code?: string | number) {
		this.handleError({
			type,
			message,
			code,
			timestamp: Date.now(),
		})
	}
}

/**
 * 性能监控工具
 */
export class PerformanceMonitor {
	private static instance: PerformanceMonitor
	private marks: Map<string, number> = new Map()

	private constructor() {
		this.setupPerformanceObserver()
	}

	static getInstance(): PerformanceMonitor {
		if (!PerformanceMonitor.instance) {
			PerformanceMonitor.instance = new PerformanceMonitor()
		}
		return PerformanceMonitor.instance
	}

	/**
	 * 设置性能观察器
	 */
	private setupPerformanceObserver() {
		if ('PerformanceObserver' in window) {
			// 监控长任务
			const longTaskObserver = new PerformanceObserver((list) => {
				list.getEntries().forEach((entry) => {
					if (entry.duration > 50) {
						// 超过50ms的任务
						console.warn('Long task detected:', {
							duration: entry.duration,
							startTime: entry.startTime,
						})
					}
				})
			})

			longTaskObserver.observe({ entryTypes: ['longtask'] })

			// 监控导航性能
			const navigationObserver = new PerformanceObserver((list) => {
				list.getEntries().forEach((entry) => {
					console.log('Navigation performance:', {
						domContentLoaded:
							(entry as any).domContentLoadedEventEnd - entry.startTime,
						loadComplete: (entry as any).loadEventEnd - entry.startTime,
					})
				})
			})

			navigationObserver.observe({ entryTypes: ['navigation'] })
		}
	}

	/**
	 * 开始性能标记
	 */
	startMark(name: string) {
		this.marks.set(name, performance.now())
	}

	/**
	 * 结束性能标记并返回耗时
	 */
	endMark(name: string): number {
		const startTime = this.marks.get(name)
		if (startTime === undefined) {
			console.warn(`Performance mark '${name}' not found`)
			return 0
		}

		const duration = performance.now() - startTime
		this.marks.delete(name)

		console.log(`Performance [${name}]: ${duration.toFixed(2)}ms`)
		return duration
	}

	/**
	 * 获取页面性能指标
	 */
	getPagePerformance() {
		if (!performance.timing) return null

		const timing = performance.timing
		return {
			// DNS查询耗时
			dnsLookup: timing.domainLookupEnd - timing.domainLookupStart,
			// TCP连接耗时
			tcpConnect: timing.connectEnd - timing.connectStart,
			// 首字节时间
			ttfb: timing.responseStart - timing.navigationStart,
			// DOM解析耗时
			domParse: timing.domContentLoadedEventEnd - timing.domLoading,
			// 页面完全加载时间
			pageLoad: timing.loadEventEnd - timing.navigationStart,
		}
	}
}

// 导出单例实例
export const errorHandler = ErrorHandler.getInstance()
export const performanceMonitor = PerformanceMonitor.getInstance()
